#include "DeterministicSelectionStrategy.h"
#include "Chromosome.h"
#include "math.h"

DeterministicSelectionStrategy::DeterministicSelectionStrategy() : SelectionStrategy(),
                            currentIndex(0),
                            retCount(0),
                            listSizeReached(false)
{
    TRACE_FUNC
}

Chromosome* DeterministicSelectionStrategy::selectOne(const QList<Chromosome*>& chromosomeList)
{
    TRACE_FUNC_ENTRY

    Chromosome* chromosome;

    //qDebug() << "listSizeReached: " << listSizeReached;

    if(listSizeReached)
    {
        if(tmpList.isEmpty())
            createTempList(chromosomeList);

        //qDebug() << "chromosomeList index: " << tmpList.last().second;
        chromosome = chromosomeList[tmpList.last().second];
        tmpList.removeLast();
    }
    else
    {
        //TODO not need to count it every time
        double averageGenerationFitness = countAverageGenerationFitness(chromosomeList);
        //qDebug() << "averageGenerationFitness: " << averageGenerationFitness;

        double expectedCount = chromosomeList[currentIndex]->getFitness()/averageGenerationFitness;

        //qDebug() << "expected: " << expectedCount;
        //qDebug() << "currentIndex: " << currentIndex;
        //qDebug() << "retCount: " << retCount;

        chromosome = chromosomeList[currentIndex];
        ++retCount;

        if(floor(expectedCount) == 0)
        {
            //qDebug() << "reached < 1 expected";
            listSizeReached = true;
        }
        else if(retCount >= floor(expectedCount))
        {
            //qDebug() << "change index";
            retCount = 0;
            ++currentIndex;

            if(currentIndex > chromosomeList.size()-1)
                listSizeReached = true;
        }

    }

    TRACE_FUNC_EXIT
    return chromosome;
}

void DeterministicSelectionStrategy::resetTempData()
{
    TRACE_FUNC_ENTRY
    currentIndex = 0;
    retCount = 0;
    listSizeReached = false;
    tmpList.clear();
    TRACE_FUNC_EXIT
}

void DeterministicSelectionStrategy::createTempList(const QList<Chromosome*>& chromosomeList)
{
    //TODO not need to count it every time
    double averageGenerationFitness = countAverageGenerationFitness(chromosomeList);
    //qDebug() << "averageGenerationFitness: " << averageGenerationFitness;

    for(int i=0;i<chromosomeList.size();++i)
    {
        double expectedCount = chromosomeList[i]->getFitness()/averageGenerationFitness;
        //qDebug() << "index: " << i << " expectedCount: " << expectedCount;
        expectedCount -= floor(expectedCount);

        //qDebug() << "expectedCount modified: " << expectedCount;
        QPair<double, int> pair(expectedCount , i);
        tmpList.append(pair);
    }

    qSort(tmpList.begin(), tmpList.end());

    //for(int i=0;i<tmpList.size();++i)
    //    qDebug() << i << ": " << tmpList[i].first << " " << tmpList[i].second;
}
